package wave

import (
	"encoding/binary"
	"os"
)

// ReverseBytes reverse bytes slice.
func ReverseBytes(s []byte) {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

// Tag wave header reader utils.
type Tag struct {
	file *os.File
	swap bool
	tag  []byte
}

// NewTag make a Tag
func NewTag(file *os.File) *Tag {
	return &Tag{
		file: file,
		swap: false,
		tag:  []byte{},
	}
}

// Expect4ByteTag expected 4 specified bytes.
func (tag *Tag) Expect4ByteTag(expected []byte) bool {
	_tag := make([]byte, 4)
	n, err := tag.file.Read(_tag)
	if err != nil && n != 4 {
		panic("expected 4 bytes")
	}
	if string(_tag) != string(expected) {
		panic("expected " + string(expected) + " , get " + string(_tag))
	}
	copy(tag.tag, _tag)
	return true
}

// Read4ByteTag read 4 byte tag
func (tag *Tag) Read4ByteTag() {
	_tag := make([]byte, 4)
	n, err := tag.file.Read(_tag)
	if err != nil && n != 4 {
		panic("expected to read 4 bytes")
	}
	copy(tag.tag, _tag)

}

// ReadUint32 read uint32
func (tag *Tag) ReadUint32() uint32 {
	result := make([]byte, 4)
	n, err := tag.file.Read(result)
	if n != 4 && err != nil {
		panic("expected to read 4 bytes")
	}
	if tag.swap {
		ReverseBytes(result)
	}
	if IsLittleEndian() {
		return uint32(binary.LittleEndian.Uint32(result))
	}
	return uint32(binary.BigEndian.Uint32(result))
}

// ReadUint16 read uint16
func (tag *Tag) ReadUint16() uint16 {
	result := make([]byte, 2)
	n, err := tag.file.Read(result)
	if n != 2 && err != nil {
		panic("expected to read 2 bytes")
	}
	if tag.swap {
		ReverseBytes(result)
	}
	if IsLittleEndian() {
		return uint16(binary.LittleEndian.Uint16(result))
	}
	return uint16(binary.BigEndian.Uint16(result))
}
